home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / asm_term.zip / TERM.ASM < prev    next >
Assembly Source File  |  1988-04-18  |  14KB  |  382 lines

  1. ;                   /-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\
  2. ;                   |                                     |
  3. ;                   |  Terminal in assembler, A86 format  |
  4. ;                   |     Interrupt driven reception      |
  5. ;                   |   -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-   |
  6. ;                   |        Weefus on GEnie or           |
  7. ;                   |    Keith Rolland    1:321/112.5     |
  8. ;                   |        (!) Copywrong 1988           |
  9. ;                   |                                     |
  10. ;                   \-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-/
  11. ;
  12. ;
  13. jmp BEGIN_PRG       ;jump over our data area to the real beginning
  14.  
  15. MESSAGE1 db 07h,0dh,0ah,0ah,0ah,"Press <alt>-q to quit.......",0dh,0ah,0ah,"$"
  16. MESSAGE2 db "          Arrgg, I spent HOW much time on this?!?         $"
  17.  
  18. BUFFER_BOT equ $
  19. BUFFER db 0ffh DUP 00h        ;the actual incoming buffer, 255 bytes
  20. BUFFER_TOP equ $
  21.  
  22. BUFFER_TAIL dw 0000h          ;used to control where characters are put
  23. BUFFER_HEAD dw 0000h          ;into and taken from the buffer
  24.  
  25. LINE_CTL_REG = 03fbh          ;various memory locations for rs232 registers
  26. MODEM_CTL_REG = 03fch
  27. LINE_STAT_REG = 03fdh
  28. MODEM_STAT_REG = 03feh
  29. CHAR_HOLDING_REG = 03f8h
  30.  
  31. BOX_TLCOR = 0c9h                   ;Ascii graphic characters used for
  32. BOX_TRCOR = 0bbh                   ;making the box.
  33. BOX_BLCOR = 0c8H                   ;TLCOR = TopLeftCORner and so on....
  34. BOX_BRCOR = 0bch
  35. BOX_VERT  = 0bah
  36. BOX_HORZ  = 0cdh
  37. SPACE     = 020h
  38.  
  39. SCROLL_COUNT db 00h
  40. ;============================================================================
  41. BEGIN_PRG:
  42. mov w[BUFFER_TAIL], offset BUFFER       ;set up buffer pointer variables
  43. mov w[BUFFER_HEAD], offset BUFFER       ;for our circular buffer
  44.  
  45. call CLEAR_SCREEN   ;routine that will....... (guess :)
  46.  
  47. call BOX_MAKE       ;make our superneato ascii box and message
  48.  
  49. call SETUP          ;set up rs232 and new interrupt routines
  50.  
  51. ;*****************************************************************************
  52. MAIN_LOOP:
  53. call CHECK_INCOMING ;check the buffer, and print any waiting characters
  54. call CHECK_OUTGOING ;see if any keystrokes are waiting in the keyboard queue
  55. jnc MAIN_LOOP       ;if carry flag not set, jump to main loop
  56. ;*****************************************************************************
  57. cli                 ;the carry flag is set, indicating an exit request
  58. in al,021h          ;reset the com1 interrupt bit in the IMR
  59. or al,010h          ;so that no more com1 ints are performed
  60. out 021h,al         ;put it back
  61. mov dx,LINE_CTL_REG ;line control reg
  62. in al,dx            ;get byte
  63. and al,07fh         ;clear bit 7, com1 interrupt enable bit
  64. out dx,al           ;put it back
  65. mov al,00h          ;tell the modem we no longer will be operating.....
  66. mov dx,MODEM_CTL_REG ;clear modem control reg
  67. out dx,al           ;do it
  68. sti                 ;re-enable interrupts
  69. int 20h             ;standard end program interrupt
  70. ;-----------------------
  71. SETUP:              ;direct set-up of registers, no bios or dos calls
  72.             ;my mom said it was ok............:)
  73. mov dx,LINE_CTL_REG ;point to the line control register, it controls a lot.
  74. mov al,080h         ;turn on bit 7
  75. out dx,al           ;send byte
  76. dec dx              ;point to msb of baud rate divisor
  77. dec dx
  78. mov al,00h          ;msb for any rate > 1200 baud is 00h
  79. out dx,al           ;send byte
  80. dec dx              ;point to lsb of baud rate divisor
  81. mov al,060h         ;lsb for 1200 bps is 60h, use 30h for 2400 bps
  82. out dx,al           ;send byte
  83. mov dx,LINE_CTL_REG ;line control register
  84. mov al,0ah          ;7/E/1 settings=0ah /use 03h for 8/n/1
  85. out dx,al           ;send byte
  86.  
  87. mov dx,offset NEW_INT ;point com1 interrupt to our new routine, NEW_INT
  88. mov al,0ch          ;interrupt to replace = COM1
  89. mov ah,025h         ;dos function number for change-a-vector
  90. int 21h             ;call dos to change vector
  91.  
  92. in al,021h          ;this will enable interrupts by setting the
  93. and al,0efh         ;com1 interrupt bit in the IMR (don't ask! :)
  94. out 021h,al         ;IMR is the Interrupt Mask Register
  95. cli                 ;we don't want to be disturbed during this...
  96. mov dx,LINE_CTL_REG ;point to line control register, rs232
  97. in al,dx            ;get byte
  98. and al,07fh         ;set high bit
  99. out dx,al           ;and put it back
  100. dec dx
  101. dec dx              ;move to the rs232 interrupt enable register
  102. mov al,01h          ;set it to interrupt when data recieved
  103. out dx,al           ;put it back
  104. inc dx
  105. inc dx              ;move to modem control register |could have done ....|
  106. inc dx              ;set it for using interrupts    |mov dx,MODEM_CTL_REG|
  107. mov al,08h          ;bit #3 high
  108. out dx,al           ;put it back
  109. sti                 ;re-enable normal interrupts
  110. mov dx,offset MESSAGE1 ;print how-to-exit message
  111. mov ah,09h             ;via dos
  112. int 21h
  113. ret                    ;end of set-up
  114. ;-----------------------
  115. CHECK_INCOMING:
  116. mov bx,w[BUFFER_TAIL]  ;check to see if anything
  117. cmp bx,w[BUFFER_HEAD]  ;is in the buffer....
  118. je ret                 ;jump if nothing ready
  119. mov al,b[bx]           ;character is ready, get it in al
  120. inc bx
  121. cmp bx,BUFFER_TOP      ;if buffer_head is at the top of the
  122. jne >L17               ;buffer, we must point it to the other end
  123. mov bx,BUFFER_BOT
  124. L17:
  125. mov w[BUFFER_TAIL],bx  ;place new buffer tail in storage
  126. cmp al,1bh          ;is char an <escape>?
  127. jne >L13            ;no, so jump, otherwise.....
  128. mov al,0dbh         ;change it to a graphic char. No vt100/ansi stuff allowed!
  129. L13:                ;      this is a *real* simple program! :)
  130. mov dl,al           ;dos wants the char in dl to print it
  131. mov ah,02h          ;dos print function
  132. int 21h             ;call dos
  133. ret                 ;end check_incoming
  134. ;-----------------------
  135. CHECK_OUTGOING:
  136. call CK_FOR_KEY     ;subroutine checks for keypress via bios interrupt
  137. je ret              ;no key pressed, return to main_loop
  138. jnc >L4             ;no exit request pending so jump ahead
  139. ret                 ;carry set, so just return and main_loop will act on it
  140. L4:
  141. push bx             ;push these on stack
  142. push dx             ;as they will be used
  143. push cx             ;here internally
  144. mov bl,al           ;put keypress in bl temporarily
  145. mov dx,MODEM_CTL_REG ;point to modem control register
  146. mov al,0bh          ;tell modem we want to send
  147. out dx,al           ;put byte in the register
  148. mov dx,MODEM_STAT_REG ;point to modem status register
  149. WAIT_FOR_CLR:
  150. in al,dx            ;get modem status
  151. test al,010h        ;test for modems 'clear-to-send' line (bit #4)
  152. jne >L5             ;no problems so jump
  153. loop WAIT_FOR_CLR   ;wait for ok (modem is presently busy)
  154. L5:
  155. mov dx,LINE_STAT_REG ;point to line status register
  156. OK_STATUS:
  157. in al,dx            ;get status byte
  158. test al,020h        ;test bit #5, 'transmit register empty'
  159. jne >L6             ;it's empty,so it's ready for another character
  160. loop OK_STATUS      ;it is full, so loop until it is empty
  161. L6:
  162. mov al,bl           ;put keypress in al
  163. mov dx,CHAR_HOLDING_REG ;point to transmitter holding register
  164. out dx,al           ;put keypress in transmit register, where it
  165. pop cx              ;automagicly will be sent upon it's way
  166. pop dx              ;restore these from stack
  167. pop bx
  168. ret                 ;end check_outgoing
  169. ;-----------------------
  170. NEW_INT:            ;Our New Interrupt Handler
  171. cli                 ;this interrupt routine is called by the hardware
  172. push ax             ;every time a character is recieved via rs232
  173. push bx
  174. push dx             ;save registers on stack
  175. push si
  176. push ds
  177. mov ax,cs           ;make sure data seg is code seg
  178. mov ds,ax
  179. mov dx,CHAR_HOLDING_REG ;recieve register, the incoming char is held here
  180. in al,dx              ;get byte, the incoming character, from register
  181. mov bx,w[BUFFER_HEAD] ;get present buffer head position in bx
  182. mov si,bx             ;and then increase bx to point to where
  183. inc bx                ;the next character will be placed
  184. cmp bx,BUFFER_TOP   ;if BUFFER_HEAD=BUFFER_TOP, we make it BUFFER_BOT
  185. jne >L10            ;next char goes somewhere